package com.niguang.govt.admin.api.service.impl;

import com.alicp.jetcache.anno.CacheType;
import com.alicp.jetcache.anno.Cached;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.niguang.govt.admin.api.entity.Area;
import com.niguang.govt.admin.api.entity.GovtUser;
import com.niguang.govt.admin.api.mapper.GovtUserMapper;
import com.niguang.govt.admin.api.service.GovtUserService;
import com.niguang.govt.admin.api.vo.AreaTree;
import com.niguang.govt.admin.common.constant.ResultCode;
import com.niguang.govt.admin.common.pojo.Result;
import com.niguang.govt.admin.common.util.ApiTokenUtils;
import com.niguang.govt.admin.common.util.EncryptionMD5;
import org.apache.commons.lang3.StringUtils;
import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 政府后台用户 服务实现类
 * </p>
 *
 * @author 12380
 * @since 2018-12-13
 */
@Service
public class GovtUserServiceImpl extends ServiceImpl<GovtUserMapper, GovtUser> implements GovtUserService {

    @Resource
    private ApiTokenUtils apiTokenUtils;

    /**
     * 处理用户拥有的城市权限
     *
     * @param cityAuth 多个用逗号分隔
     * @return
     */
    @Cached(name = "govt-admin-getCityAuthList:", key = "#cityAuth", expire = 1, cacheType = CacheType.REMOTE, timeUnit = TimeUnit.DAYS)
    private static List<String> getCityAuthList(String cityAuth) {
        if (StringUtils.isBlank(cityAuth)) {
            return null;
        }
        List<String> list = Arrays.asList(cityAuth.split(","));
        String cityStr = "";
        for (String city : list) {
            cityStr += getCity(city, "");
        }
        return Arrays.asList(StringUtils.split(cityStr, ","))
                .parallelStream()
                .distinct()
                .collect(Collectors.toList());
    }

    private static String getCity(String city, String cityStr) {
        if (StringUtils.isBlank(cityStr)) {
            cityStr += city + ",";
        }
        if (StringUtils.length(city) > 2) {
            city = StringUtils.substring(city, 0, StringUtils.length(city) - 2);
            cityStr += city + ",";
            return getCity(city, cityStr);
        }
        return cityStr;
    }

    @Override
    public Result<Boolean> addUser(GovtUser govtUser) {
        int count = govtUser.selectCount(new QueryWrapper<GovtUser>().lambda().eq(GovtUser::getUserAccount, govtUser.getUserAccount()));
        if (count > 0) {
            return Result.build(ResultCode.PARAM_ERROR, "账号[" + govtUser.getUserAccount() + "]已创建，请勿重复创建！");
        }
        govtUser.setUserPwd(EncryptionMD5.getMD5("123456"));
        govtUser.setLeve(2);
        return Result.success(govtUser.insert());
    }

    @Override
    public Result loginUser(String userAccount, String userPwd) {
        GovtUser govtUser = new GovtUser().selectOne(new QueryWrapper<GovtUser>().lambda().eq(GovtUser::getUserAccount, userAccount));
        if (ObjectUtils.isEmpty(govtUser)) {
            return Result.build(ResultCode.PARAM_ERROR, "账号不存在，请注册后登录！");
        }
        if (!StringUtils.equalsAnyIgnoreCase(EncryptionMD5.getMD5(userPwd), govtUser.getUserPwd())) {
            return Result.build(ResultCode.PARAM_ERROR, "密码不正确！");
        }
        List<String> cityAuthList = ((GovtUserServiceImpl) AopContext.currentProxy()).getCityAuthList(govtUser.getCityAuth());
        List<AreaTree> areaTree = ((GovtUserServiceImpl) AopContext.currentProxy()).getAreaTree(cityAuthList);
        String token = apiTokenUtils.createToken(govtUser.getId());
        govtUser.setAuthorization(token);
        govtUser.setAreaTree(areaTree);
        return Result.success(govtUser);
    }

    @Cached(name = "govt-admin-getAreaTree:", key = "#cityList", expire = 30, cacheType = CacheType.REMOTE, timeUnit = TimeUnit.DAYS)
    public List<AreaTree> getAreaTree(List<String> cityList) {
        List<Area> list;
        if (CollectionUtils.isEmpty(cityList)) {
            list = new Area().selectList(null);
        } else {
            list = new Area().selectList(new QueryWrapper<Area>().lambda().in(Area::getId, cityList));
        }
        Map<Integer, List<AreaTree>> groupBy = list.stream()
                .map(it ->
                        new AreaTree(it.getId(), it.getPid(), it.getAreaName(), null)
                ).collect(Collectors.groupingBy(AreaTree::getPid));
        return getTree(groupBy, 0);
    }

    private List<AreaTree> getTree(Map<Integer, List<AreaTree>> group, Integer pid) {
        List<AreaTree> list = group.get(pid);
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>();
        }
        list.forEach(it -> it.setChildren(getTree(group, it.getId())));
        return list;
    }
}
